const dayjs = require('dayjs');
const qpay = require('../services/qpay');
const logger = require('../config/logger');
const crypto = require('crypto');
const url = require('url');

// 验证和清理URL
function sanitizeCallbackUrl(baseUrl) {
  try {
    // 解析基础URL
    const parsedUrl = new URL(baseUrl);
    
    // 只允许 http 或 https 协议
    if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
      throw new Error('不支持的URL协议');
    }

    // 移除URL中的敏感信息
    parsedUrl.username = '';
    parsedUrl.password = '';
    
    // 确保路径以 / 开头
    if (!parsedUrl.pathname.startsWith('/')) {
      parsedUrl.pathname = '/' + parsedUrl.pathname;
    }

    // 移除URL中的特殊字符
    parsedUrl.pathname = parsedUrl.pathname.replace(/[^a-zA-Z0-9-_/]/g, '');
    
    return parsedUrl.toString();
  } catch (error) {
    logger.error('回调URL验证失败', { 
      baseUrl,
      error: error.message 
    });
    throw new Error('无效的回调URL');
  }
}

async function recharge(request, reply) {
  const { amount, paymentMethod } = request.body;
  try {
    // 检查用户认证状态
    if (!request.user || !request.user.id) {
      logger.error('充值失败：用户未认证', { request: request.body });
      return reply.code(401).send({ error: '请先登录' });
    }

    // 检查用户是否存在
    const user = await this.prisma.user.findUnique({
      where: { id: request.user.id }
    });

    if (!user) {
      logger.error('充值失败：用户不存在', { userId: request.user.id });
      return reply.code(404).send({ error: '用户不存在' });
    }

    // 创建充值记录
    const recharge = await this.prisma.recharge.create({
      data: {
        userId: user.id,
        amount,
        rechargeStatus: '待支付',
        paymentMethod: paymentMethod || 'qpay',
        createdAt: new Date(),
        updatedAt: new Date()
      }
    });

    // 生成安全的时间戳和签名
    const timestamp = Date.now();
    const nonce = crypto.randomBytes(16).toString('hex');
    const signature = crypto
      .createHmac('sha256', process.env.QPAY_SECRET_KEY)
      .update(`${timestamp}${nonce}`)
      .digest('hex');

    // 构造安全的回调URL
    const baseCallbackUrl = sanitizeCallbackUrl(process.env.BASE_URL);
    const callbackUrl = new URL('/payments/recharge/callback', baseCallbackUrl);
    
    
    // 添加安全参数
    callbackUrl.searchParams.append('timestamp', timestamp);
    callbackUrl.searchParams.append('nonce', nonce);
    callbackUrl.searchParams.append('signature', signature);

    callbackUrl.searchParams.append('rechargeId', recharge.id);
    // 调用QPay创建发票
    const qpayResult = await qpay.createInvoice({
      invoice_code: process.env.QPAY_INVOICE_CODE,
      sender_invoice_no: `R${recharge.id}`,
      invoice_receiver_code: "terminal",
      invoice_description: `User ${user.phone} recharged ${amount} MNT`,
      amount: amount,
      callback_url: callbackUrl.toString(),
      sender_branch_code: "ONLINE",
      sender_staff_code: "SYSTEM",
      invoice_receiver_data: {
        register: user.phone || "",
        name: user.name || "",
        email: user.email || "",
        phone: user.phone || ""
      }
    });

    // 更新充值记录，添加QPay发票信息
    const updatedRecharge = await this.prisma.recharge.update({
      where: { id: recharge.id },
      data: {
        qpayInvoiceId: qpayResult.invoice_id,
        qpayQrText: qpayResult.qr_text,
        qpayQrImage: qpayResult.qr_image,
        qpayPaymentUrl: qpayResult.qPay_shortUrl
      }
    });

    logger.info('充值记录创建成功', { 
      rechargeId: recharge.id,
      userId: user.id,
      amount,
      paymentMethod,
      qpayInvoiceId: qpayResult.invoice_id
    });

    return reply.send({
      ...updatedRecharge,
      qrText: qpayResult.qr_text,
      qrImage: qpayResult.qr_image,
      paymentUrl: qpayResult.qPay_shortUrl,
      urls: qpayResult.urls
    });  
  } catch (error) {
    logger.error('充值失败：系统错误', {
      error: error.message,
      stack: error.stack,
      userId: request.user?.id,
      amount,
      paymentMethod
    });
    return reply.code(500).send({ error: '处理充值失败' });
  }
}

// 验证QPay回调签名
function verifyQPayCallbackSignature(request, expectedSignature) {
  const { timestamp, nonce } = request.query; // 获取回调参数
  
  // 确保所有必要的签名参数都存在
  if (!timestamp || !nonce || !expectedSignature) {
    logger.error('签名验证失败：缺少必要参数', { query: request.query, ip: request.ip });
    return false;
  }

  // 验证时间戳是否在合理范围内（例如，5分钟内）
  const now = Date.now();
  if (Math.abs(now - parseInt(timestamp)) > 300000) { // 300000毫秒 = 5分钟
    logger.error('签名验证失败：时间戳过期', { timestamp, ip: request.ip });
    return false;
  }

  // 构建用于生成签名的字符串，与生成时保持一致
  const signString = `${timestamp}${nonce}`;
  
  const calculatedSignature = crypto
    .createHmac('sha256', process.env.QPAY_SECRET_KEY)
    .update(signString)
    .digest('hex');

  // 使用timingSafeEqual防止时序攻击
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(calculatedSignature)
  );
}

async function handleRechargeCallback(request, reply) {
  const { rechargeId, timestamp, nonce, signature } = request.query;

  // 保留关键的安全验证
  if (!verifyQPayCallbackSignature(request, signature)) {
    logger.error('充值回调处理失败：签名验证未通过', { query: request.query, ip: request.ip });
    return reply.code(401).send('签名验证失败');
  }

  try {
    // 根据rechargeId查询充值记录
    const recharge = await this.prisma.recharge.findUnique({
      where: { 
        id: parseInt(rechargeId, 10)
      }
    });

    if (!recharge) {
      logger.error('充值回调处理失败：未找到充值记录', { 
        rechargeId,
        query: request.query,
        ip: request.ip 
      });
      return reply.code(404).send('未找到充值记录');
    }

    // 调用QPay查询支付详情
    logger.info('开始查询QPay支付状态', {
      invoice_id: recharge.qpayInvoiceId,
      recharge_id: recharge.id,
      ip: request.ip
    });

    const paymentInfo = await qpay.checkPayment('INVOICE', recharge.qpayInvoiceId);
    
    logger.info('QPay支付状态检查结果:', paymentInfo);

    // 验证支付状态
    if (!paymentInfo || !paymentInfo.rows || paymentInfo.rows.length === 0) {
      logger.error('充值回调处理失败：未找到支付记录', {
        invoice_id: recharge.qpayInvoiceId,
        recharge_id: recharge.id,
        payment_info: paymentInfo,
        ip: request.ip
      });
      return reply.code(200).send('支付未完成');
    }

    // 获取最新的支付记录
    const latestPayment = paymentInfo.rows[0];
    if (latestPayment.payment_status !== 'PAID') {
      logger.error('充值回调处理失败：支付未完成', {
        invoice_id: recharge.qpayInvoiceId,
        payment_status: latestPayment.payment_status,
        ip: request.ip
      });
      return reply.code(200).send('支付未完成');
    }

    // 使用事务处理数据库操作
    await this.prisma.$transaction(async (prisma) => {
      // 查找对应的充值记录
      const existingRecharge = await prisma.recharge.findFirst({
        where: {
          qpayInvoiceId: recharge.qpayInvoiceId,
          rechargeStatus: '待支付'
        }
      });

      if (!existingRecharge) {
        logger.warn('充值回调处理：未找到对应的待支付充值记录或已处理', { 
          invoice_id: recharge.qpayInvoiceId, 
          ip: request.ip 
        });
        return;
      }

      // 更新充值记录状态
      await prisma.recharge.update({
        where: { id: existingRecharge.id },
        data: {
          rechargeStatus: '已支付',
          qpayPaymentId: latestPayment.payment_id,
          updatedAt: new Date()
        }
      });

      // 更新用户余额
      await prisma.user.update({
        where: { id: existingRecharge.userId },
        data: {
          balance: {
            increment: existingRecharge.amount
          }
        }
      });

      // 创建收益记录
      await prisma.reconciliation.create({
        data: {
          type: '充值收益',
          amount: existingRecharge.amount,
          createdAt: new Date()
        }
      });
    });

    // 创建电子收据
    try {
      const rechargeAfterUpdate = await this.prisma.recharge.findFirst({ 
        where: { qpayInvoiceId: recharge.qpayInvoiceId } 
      });
      
      if (rechargeAfterUpdate && rechargeAfterUpdate.rechargeStatus === '已支付' && !rechargeAfterUpdate.ebarimtId) {
        const ebarimtResult = await qpay.createEbarimt(latestPayment.payment_id, 'CITIZEN');
        if (ebarimtResult) {
          await this.prisma.recharge.update({
            where: { id: rechargeAfterUpdate.id },
            data: {
              ebarimtId: ebarimtResult.ebarimt_id
            }
          });
          logger.info('电子收据创建成功', { 
            payment_id: latestPayment.payment_id, 
            rechargeId: rechargeAfterUpdate.id, 
            ebarimtId: ebarimtResult.ebarimt_id, 
            ip: request.ip 
          });
        }
      }
    } catch (ebarimtError) {
      logger.error('创建电子收据失败', {
        error: ebarimtError.message,
        payment_id: latestPayment.payment_id,
        invoice_id: recharge.qpayInvoiceId,
        ip: request.ip
      });
    }

    logger.info('充值回调处理成功', { 
      payment_id: latestPayment.payment_id, 
      invoice_id: recharge.qpayInvoiceId, 
      ip: request.ip 
    });
    
    return reply.send('SUCCESS');

  } catch (error) {
    logger.error('充值回调处理失败', {
      error: error.message,
      stack: error.stack,
      query: request.query,
      ip: request.ip
    });
    return reply.code(500).send('处理失败');
  }
}

async function checkPaymentStatus(request, reply) {
  const { rechargeId } = request.params;

  try {
    // 检查用户认证状态
    if (!request.user || !request.user.id) {
      logger.error('查询支付状态失败：用户未认证', { rechargeId });
      return reply.code(401).send({ error: '请先登录' });
    }

    // 查询充值记录
    const recharge = await this.prisma.recharge.findFirst({
      where: { 
        id: parseInt(rechargeId, 10),
        userId: request.user.id // 确保只能查询自己的充值记录
      }
    });

    if (!recharge) {
      logger.error('查询支付状态失败：未找到充值记录', { rechargeId });
      return reply.code(404).send({ error: '未找到充值记录' });
    }

    // 如果已经有支付ID，直接返回状态
    if (recharge.qpayPaymentId) {
      return reply.send({
        rechargeId: recharge.id,
        status: recharge.rechargeStatus,
        paymentId: recharge.qpayPaymentId,
        amount: recharge.amount,
        createdAt: recharge.createdAt,
        updatedAt: recharge.updatedAt
      });
    }

    // 检查是否有发票ID
    if (!recharge.qpayInvoiceId) {
      logger.error('查询支付状态失败：未找到发票ID', { rechargeId });
      return reply.send({
        rechargeId: recharge.id,
        status: recharge.rechargeStatus,
        amount: recharge.amount,
        createdAt: recharge.createdAt,
        updatedAt: recharge.updatedAt
      });
    }

    // 如果没有支付ID，查询QPay支付状态
    const paymentInfo = await qpay.checkPayment('INVOICE', recharge.qpayInvoiceId);
    
    if (!paymentInfo || !paymentInfo.rows || paymentInfo.rows.length === 0) {
      return reply.send({
        rechargeId: recharge.id,
        status: recharge.rechargeStatus,
        amount: recharge.amount,
        createdAt: recharge.createdAt,
        updatedAt: recharge.updatedAt
      });
    }

    // 获取最新的支付记录
    const latestPayment = paymentInfo.rows[0];
    
    // 如果支付已完成但状态未更新，更新状态
    if (latestPayment.payment_status === 'PAID' && recharge.rechargeStatus === '待支付') {
      await this.prisma.$transaction(async (prisma) => {
        // 更新充值记录状态
        await prisma.recharge.update({
          where: { id: recharge.id },
          data: {
            rechargeStatus: '已支付',
            qpayPaymentId: latestPayment.payment_id,
            updatedAt: new Date()
          }
        });

        // 更新用户余额
        await prisma.user.update({
          where: { id: recharge.userId },
          data: {
            balance: {
              increment: recharge.amount
            }
          }
        });

        // 创建收益记录
        await prisma.reconciliation.create({
          data: {
            type: '充值收益',
            amount: recharge.amount,
            createdAt: new Date()
          }
        });
      });

      // 尝试创建电子收据
      try {
        const ebarimtResult = await qpay.createEbarimt(latestPayment.payment_id, 'CITIZEN');
        if (ebarimtResult) {
          await this.prisma.recharge.update({
            where: { id: recharge.id },
            data: {
              ebarimtId: ebarimtResult.ebarimt_id
            }
          });
        }
      } catch (ebarimtError) {
        logger.error('创建电子收据失败', {
          error: ebarimtError.message,
          payment_id: latestPayment.payment_id,
          invoice_id: recharge.qpayInvoiceId
        });
      }
    }

    return reply.send({
      rechargeId: recharge.id,
      status: latestPayment.payment_status === 'PAID' ? '已支付' : recharge.rechargeStatus,
      paymentId: latestPayment.payment_id,
      amount: recharge.amount,
      createdAt: recharge.createdAt,
      updatedAt: new Date()
    });

  } catch (error) {
    logger.error('查询支付状态失败', {
      error: error.message,
      stack: error.stack,
      rechargeId
    });
    return reply.code(500).send({ error: '查询支付状态失败' });
  }
}

async function refundRecharge(request, reply) {
  const { rechargeId } = request.params;
  const { reason } = request.body;

  try {
    // 检查用户认证状态
    if (!request.user || !request.user.id) {
      logger.error('退款失败：用户未认证', { rechargeId });
      return reply.code(401).send({ error: '请先登录' });
    }

    // 查询充值记录
    const recharge = await this.prisma.recharge.findFirst({
      where: { 
        id: parseInt(rechargeId, 10),
        userId: request.user.id // 确保只能退款自己的充值
      }
    });

    if (!recharge) {
      logger.error('退款失败：未找到充值记录', { rechargeId });
      return reply.code(404).send({ error: '未找到充值记录' });
    }

    // 检查充值状态
    if (recharge.rechargeStatus !== '已支付') {
      logger.error('退款失败：充值状态不正确', { 
        rechargeId,
        status: recharge.rechargeStatus 
      });
      return reply.code(400).send({ error: '只能退款已支付的充值' });
    }

    // 检查是否已经退款
    if (recharge.rechargeStatus === '已退款') {
      logger.error('退款失败：充值已退款', { rechargeId });
      return reply.code(400).send({ error: '该充值已退款' });
    }

    try {
      // 调用QPay进行退款
      const refundResult = await qpay.refundPayment({
        payment_id: recharge.qpayPaymentId,
        amount: recharge.amount,
        reason: reason || '用户申请退款'
      });

      // 验证退款结果
      if (!refundResult || refundResult.status !== 'SUCCESS') {
        logger.error('退款失败：QPay退款未成功', {
          rechargeId,
          qpayResult: refundResult
        });
        return reply.code(400).send({ error: '退款处理失败，请稍后重试' });
      }

      // 使用事务处理数据库操作
      await this.prisma.$transaction(async (prisma) => {
        // 更新充值记录状态
        await prisma.recharge.update({
          where: { id: recharge.id },
          data: {
            rechargeStatus: '已退款',
            refundReason: reason,
            refundTime: new Date(),
            qpayRefundId: refundResult.refund_id, // 保存QPay退款ID
            updatedAt: new Date()
          }
        });

        // 更新用户余额
        await prisma.user.update({
          where: { id: recharge.userId },
          data: {
            balance: {
              decrement: recharge.amount
            }
          }
        });

        // 创建退款记录
        await prisma.reconciliation.create({
          data: {
            type: '充值退款',
            amount: -recharge.amount,
            description: reason,
            qpayRefundId: refundResult.refund_id, // 保存QPay退款ID
            createdAt: new Date()
          }
        });
      });

      logger.info('充值退款成功', { 
        rechargeId,
        userId: recharge.userId,
        amount: recharge.amount,
        reason,
        qpayRefundId: refundResult.refund_id
      });

      return reply.send({
        rechargeId: recharge.id,
        status: '已退款',
        amount: recharge.amount,
        refundTime: new Date(),
        reason,
        qpayRefundId: refundResult.refund_id
      });

    } catch (qpayError) {
      // 处理QPay特定的错误
      if (qpayError.response?.data?.error === 'PAYMENT_SETTLED') {
        logger.error('退款失败：支付已结算', {
          rechargeId,
          paymentId: recharge.qpayPaymentId
        });
        return reply.code(400).send({
          error: '该笔支付已结算，无法通过系统直接退款',
          code: 'PAYMENT_SETTLED',
          message: '请联系客服处理退款'
        });
      }

      // 处理其他QPay错误
      logger.error('退款失败：QPay处理错误', {
        error: qpayError.message,
        rechargeId,
        paymentId: recharge.qpayPaymentId
      });
      return reply.code(400).send({
        error: '退款处理失败',
        code: qpayError.response?.data?.error || 'UNKNOWN_ERROR',
        message: '请稍后重试或联系客服'
      });
    }

  } catch (error) {
    logger.error('充值退款失败', {
      error: error.message,
      stack: error.stack,
      rechargeId
    });
    return reply.code(500).send({
      error: '系统处理失败',
      code: 'SYSTEM_ERROR',
      message: '请稍后重试'
    });
  }
}

module.exports = {
  recharge,
  handleRechargeCallback,
  checkPaymentStatus,
  refundRecharge
};